﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AccountEditorViewModel.cs" company="Concept Architecture">
//   (c) 2010 Muhammad Umer Farooq
// </copyright>
// <summary>
//   Defines the <seealso cref="AccountEditorViewModel" /> type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Hisaab.Client.Modules.Core.Account.ViewModel
{
    using System;
    using System.Collections.ObjectModel;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using System.Windows.Input;
    using System.Windows.Media.Imaging;
    using Business.Interfaces;
    using Common.BaseClasses;
    using Common.Services;
    using Hisaab.Common;
    using Microsoft.Practices.Prism.Commands;
    using Microsoft.Practices.Prism.Regions;
    using Microsoft.Practices.ServiceLocation;
    using Model;

    /// <summary>
    /// Defines the <seealso cref="AccountEditorViewModel"/> type.
    /// </summary>
    public class AccountEditorViewModel : WindowViewModel, INavigationAware, IRegionMemberLifetime
    {
        #region Data Members

        /// <summary>
        /// Session manager
        /// </summary>
        private readonly ISession _session;

        /// <summary>
        /// Account manager
        /// </summary>
        private readonly IAccountManager _accountManager;

        /// <summary>
        /// The type manager
        /// </summary>
        private readonly ITypeManager _typeManager;

        /// <summary>
        /// Account types
        /// </summary>
        private ObservableCollection<AccountType> _accountTypes;

        /// <summary>
        /// Selected account
        /// </summary>
        private Account _selectedAccount;

        /// <summary>
        /// Member variable _saveCommand
        /// </summary>
        private ICommand _saveCommand;

        #endregion Data Members

        #region Constructors and Initializers

        /// <summary>
        /// Initializes a new instance of the <see cref="AccountEditorViewModel"/> class.
        /// </summary>
        public AccountEditorViewModel()
            : this(
            ServiceLocator.Current.GetInstance<IAccountManager>(),
            ServiceLocator.Current.GetInstance<ITypeManager>(),
            ServiceLocator.Current.GetInstance<ISession>())
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AccountEditorViewModel"/> class.
        /// </summary>
        /// <param name="accountManager">The account manager.</param>
        /// <param name="typeManager">The type manager</param>
        /// <param name="session">The sesstion</param>
        public AccountEditorViewModel(IAccountManager accountManager, ITypeManager typeManager, ISession session)
        {
            Contract.Requires<ArgumentNullException>(accountManager != null);
            Contract.Requires<ArgumentNullException>(typeManager != null);
            Contract.Requires<ArgumentNullException>(session != null);

            _accountManager = accountManager;
            _typeManager = typeManager;
            _session = session;
            Title = "Account Editor";
            Icon = new BitmapImage(new Uri("pack://application:,,,/Hisaab.Client.Common;component/Resources/Images/16/account.png"));
        }

        #endregion Constructors and Initializers

        #region Properties

        /// <summary>
        /// Gets or sets the selected account.
        /// </summary>
        /// <value>
        /// The selected account.
        /// </value>
        public Account SelectedAccount
        {
            get
            {
                return _selectedAccount;
            }

            set
            {
                if (value != null && _selectedAccount != value)
                {
                    _selectedAccount = value;
                    RaisePropertyChangedEvent("SelectedAccount");
                }
            }
        }

        /// <summary>
        /// Gets the Account Types.
        /// </summary>
        public ObservableCollection<AccountType> AccountTypes
        {
            get
            {
                if (_accountTypes == null)
                {
                    _accountTypes = new ObservableCollection<AccountType>(_typeManager.ListAccountTypes().Select(x => x.Map<Business.Entities.AccountType, AccountType>()));
                }

                return _accountTypes;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [new account].
        /// </summary>
        /// <value>
        ///   <c>true</c> if [new account]; otherwise, <c>false</c>.
        /// </value>
        public bool IsNewAccount { get; set; }

        /// <summary>
        /// Gets the save command.
        /// </summary>
        public ICommand SaveCommand
        {
            get
            {
                if (_saveCommand == null)
                {
                    _saveCommand = new DelegateCommand(SaveAccount, CanSaveAccount);
                }

                return _saveCommand;
            }
        }

        /// <summary>
        /// Gets a value indicating whether to keep alive
        /// </summary>
        /// <value><c>true</c> if keep alive; otherwise, <c>false</c>.</value>
        public bool KeepAlive
        {
            get { return false; }
        }

        #endregion Properties

        #region Public Methods

        /// <summary>
        /// Saves the account.
        /// </summary>
        public void SaveAccount()
        {
            if (IsNewAccount)
            {
                SelectedAccount.UserId = _session.LoggedUser;
                _accountManager.Add(SelectedAccount.Map<Account, Business.Entities.Account>());
            }
            else
            {
                _accountManager.Update(SelectedAccount.Map<Account, Business.Entities.Account>());
            }
        }

        /// <summary>
        /// Determines whether this instance [can save account] the specified obj.
        /// </summary>
        /// <returns>
        /// True if this instance can save account the specified obj; otherwise, false.
        /// </returns>
        public bool CanSaveAccount()
        {
            return true;
        }

        #endregion Public Methods

        #region Implementation of INavigationAware

        /// <summary>
        /// Called when [navigated to].
        /// </summary>
        /// <param name="navigationContext">The navigation context.</param>
        public void OnNavigatedTo(NavigationContext navigationContext)
        {
            if (navigationContext.Parameters["ID"] != null)
            {
                IsNewAccount = false;
                int id = int.Parse(navigationContext.Parameters["ID"]);
                SelectedAccount = _accountManager.GetById(id).Map<Business.Entities.Account, Account>();
            }
            else
            {
                IsNewAccount = true;
                SelectedAccount = new Account { InitialBalanceDate = DateTime.Today };
            }

            SelectedAccount.Dirty = false;
            CommandManager.InvalidateRequerySuggested();
        }

        /// <summary>
        /// Determines whether [is navigation target] [the specified navigation context].
        /// </summary>
        /// <param name="navigationContext">The navigation context.</param>
        /// <returns>
        ///   <c>true</c> if [is navigation target] [the specified navigation context]; otherwise, <c>false</c>.
        /// </returns>
        public bool IsNavigationTarget(NavigationContext navigationContext)
        {
            return false;
        }

        /// <summary>
        /// Called when [navigated from].
        /// </summary>
        /// <param name="navigationContext">The navigation context.</param>
        public void OnNavigatedFrom(NavigationContext navigationContext)
        {
        }

        #endregion Implementation of INavigationAware
    }
}